package org.nabc.generate;

import lombok.extern.slf4j.Slf4j;
import org.nabc.configuration.DataSource;
import org.nabc.configuration.FileConfiguration;
import org.nabc.core.DataBaseOperation;
import org.nabc.core.builder.TemplateGenerateTaskBuilder;
import org.nabc.core.creator.TemplateGenerateTaskCreator;
import org.nabc.support.PropertyValues;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

@Slf4j
public class BaseGenerateFile implements GenerateFile {
    protected final DataSource dataSource;
    protected final FileConfiguration fileConfiguration;
    protected final TemplateGenerateTaskBuilder templateGenerateTaskBuilder;
    protected List<PropertyValues> propertyValuesList;
    private DataBaseOperation dataBaseOperation = new DataBaseOperation();

    public BaseGenerateFile(DataSource dataSource, FileConfiguration fileConfiguration, TemplateGenerateTaskBuilder templateGenerateTaskBuilder) {
        this.dataSource = dataSource;
        this.fileConfiguration = fileConfiguration;
        this.templateGenerateTaskBuilder = templateGenerateTaskBuilder;
    }

    private void before() {
        log.info("开始读取数据库表");
        propertyValuesList = dataBaseOperation.readTableInfo(dataSource.getConnection(), fileConfiguration.getTablePrefix());
    }

    @Override
    public void generate() {
        before();
        try {
            generateOption(this.templateGenerateTaskBuilder);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void generateOption(TemplateGenerateTaskBuilder templateGenerateTaskBuilder) throws IOException, ExecutionException, InterruptedException {
        Queue<Future> futures = new LinkedList<>();
        List<AbstractRunnableTask> list = new ArrayList<>();

        TemplateGenerateTaskCreator templateGenerateTaskCreator = new TemplateGenerateTaskCreator(templateGenerateTaskBuilder);

        ExecutorService service = new ThreadPoolExecutor(4, 4, 0L,
                TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>());

        for (PropertyValues propertyValues : propertyValuesList) {
            log.info("开始表 {} 的相关文件", propertyValues.getTableName());
            list.addAll(templateGenerateTaskCreator.creator(fileConfiguration, propertyValues));
        };

        list.stream().filter(Objects::nonNull).forEach(v -> {
            futures.add(service.submit(v));
        });

        for (Future future : futures) {
            future.get();
        }

        service.shutdown();
    }
}
